<template>
  <!-- 不能用layerX,也不能用offsetX,因为鼠标碰到移动的ball会把小球当作最近定位的父元素,所以用来定位的left和top会重置为00,就会一闪一闪的-->
  <div id="controllerContainer" @mousemove="mouseMove" @mouseup="mouseUp">
    <div id="controllerBg"></div>
    <div
      id="controllerBall"
      @mousedown="mouseDown"
      @mouseup="mouseUp"
      :style="{ top: top + 'px', left: left + 'px' }"
    ></div>
  </div>
</template>

<script>
import { onMounted, ref, reactive, toRefs, computed } from "vue";

export default {
  setup() {
    let bg = {
      r: 0,
      //参照用,相对于document窗口
      centerXy: {
        x: 0,
        y: 0,
      },
    };

    //需要声明为响应式,不然left和top的计算属性不会生效
    let ball = reactive({
      r: 0,
      //左上角坐标,,相对于document窗口
      centerXy: {
        x: 0,
        y: 0,
      },
    });

    //外层fixed定位的容器
    let fixedTop = 0;
    let fixedLeft = 0;

    //因为ball的left和top会根据中心坐标的改变而改变,所以要定义成计算属性
    const left = computed(() => {
      return ball.centerXy.x - fixedLeft - ball.r;
    });
    const top = computed(() => {
      return ball.centerXy.y - fixedTop - ball.r;
    });
    onMounted(() => {
      //bgDom
      let bgDom = document.querySelector("#controllerBg");
      bg.r = bgDom.offsetWidth / 2;
      bg.centerXy.x = getLeft(bgDom) + bg.r;
      bg.centerXy.y = getTop(bgDom) + bg.r;
      console.log("bg信息", bg);

      //ballDom
      let ballDom = document.querySelector("#controllerBall");
      ball.r = ballDom.offsetWidth / 2;
      ball.centerXy = { ...bg.centerXy };
      console.log("球信息", ball);

      //外层Fixed的容器Dom
      let fixedDom = document.querySelector("#controllerContainer");
      fixedLeft = getLeft(fixedDom);
      fixedTop = getTop(fixedDom);
    });
    //获取元素位置,相对于窗口
    function getTop(e) {
      var offset = e.offsetTop;
      if (e.offsetParent != null) offset += getTop(e.offsetParent);
      return offset;
    }
    function getLeft(e) {
      var offset = e.offsetLeft;
      if (e.offsetParent != null) offset += getLeft(e.offsetParent);
      return offset;
    }

    let isMouseDown = false;
    function mouseDown() {
      isMouseDown = true;
    }
    function mouseUp() {
      isMouseDown = false;
      //重置ball中心坐标
      ball.centerXy = { ...bg.centerXy };
    }
    function mouseMove(e) {
      if (isMouseDown) {
        //背景圆心坐标
        let x1 = bg.centerXy.x;
        let y1 = bg.centerXy.y;
        //鼠标坐标
        let x2 = e.pageX;
        let y2 = e.pageY;
        //ball与背景的圆心距
        let d = bg.r - ball.r;
        //鼠标距离背景圆心的距离
        let l = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
        console.log(
          "鼠标坐标",
          { x2, y2 },
          "圆心坐标(bg)",
          { x1, y1 },
          "鼠标距离圆心l",
          l.toFixed(2),
          "边界d",
          d
        );
        //动画API,防止卡顿
        window.requestAnimationFrame(() => {
          //如果鼠标指针超出bg,ball贴边运动
          if (l >= d) {
            console.log("贴边!!");
            ball.centerXy.y = (d * (y2 - y1)) / l + y1;
            ball.centerXy.x = (d * (x2 - x1)) / l + x1;
          }
          //如果ball在bg里,ball的中心坐标就是鼠标坐标
          else if (l < d) {
            console.log("在内!!");
            ball.centerXy.x = x2;
            ball.centerXy.y = y2;
          }
          let vx = ball.centerXy.x - x1;
          let vy = ball.centerXy.y - y1;
          if (vx >= 0) {
            console.log(`向右`);
          }
          if (vx < 0) {
            console.log(`向左`);
          }
          if (vy >= 0) {
            console.log(`向上`);
          }
          if (vy < 0) {
            console.log(`向下`);
          }
          console.log(`vx:${vx},vy:${vy}`);
        });
      }
    }

    return { mouseDown, mouseUp, mouseMove, left, top };
  },
};
</script>
<style lang="scss" scoped>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

$containerSize: 400px;
$bgSize: 200px;
$ballSize: 50px;

/**
outerSize是外层容器的宽
innerSize是内容元素的宽
 */
@mixin center($outerSize, $innerSize) {
  position: absolute;
  top: ($outerSize - $innerSize)/2;
  left: ($outerSize - $innerSize)/2;
}

#controllerContainer {
  background-color: #34495e;
  width: $containerSize;
  height: $containerSize;
  position: fixed;
  bottom: 100px;
  left: 100px;

  #controllerBg {
    width: 200px;
    height: 200px;
    border: 1px solid rgb(243, 85, 22);
    border-radius: 50%;
    @include center($containerSize, $bgSize);
  }

  #controllerBall {
    width: $ballSize;
    height: $ballSize;
    background-color: #2ecc71;
    border-radius: 50%;
    cursor: pointer;
    position: absolute;
  }
}
</style>